#include <math.h>
#include <iostream>
#include <functional>

using std::cout;
using std::endl;
using std::bind;
using std::function;

//抽象类
class Figure
{
public:

    // function<void()> display;
    // function<double()> area;

    using Display = function<void()>;
    using Area = function<double()>;

    void setDisplay(Display display)
    {
        _display = display;
    }

    void setArea(Area area) 
    {
        _area = area;
    }

    void handleDisplay() const
    {
        if(_display)
        {
            _display();
        }
    }

    double handleArea() const
    {
        if(_area)
        {
            return _area(); 
        }
        return 0.0;
    }
    


    Display _display;
    Area _area;

};
  
class Rectangle
{
public:
    Rectangle(double len = 0, double width = 0)
    : _len(len)
    , _width(width)
    {
        cout << "Rectangle(double = 0, double = 0)" << endl;
    }

    void display() const
    {
        cout << "Rectangle";
    }

    double area() const
    {
        return _len * _width;
    }

    ~Rectangle()
    {
        cout << "~Rectangle()" << endl;
    }

private:
    double _len;
    double _width;

};

//Circle c1 = 10;//int ===>Circle
class Circle
{
public:
    explicit
    Circle(double radius = 0)
    : _radius(radius)
    {
        cout << "Circle(double = 0)" << endl;
    }

    void display() const
    {
        cout << "Circle";
    }

    double area() const
    {
        return 3.14 * _radius * _radius;
    }

    ~Circle()
    {
        cout << "~Circle()" << endl;
    }
private:
    double _radius;
};

class Triangle
{
public:
    Triangle(double a = 0, double b = 0, double c = 0)
    : _a(a)
    , _b(b)
    , _c(c)
    {
        cout << "Triangle(double = 0, double = 0, double = 0)" << endl;
    }

    void display() const
    {
        cout << "Triangle" ;
    }

    double area() const
    {
        double tmp = (_a + _b + _c)/2;
        return sqrt(tmp * (tmp - _a) * (tmp - _b) * (tmp -_c));
    }

    ~Triangle()
    {
        cout <<"~Triangle()" << endl;
    }
private:
    double _a;
    double _b;
    double _c;
};

void func(const Figure &ref)
{
    ref.handleDisplay();
    cout << "'s 的面积 " << ref.handleArea() << endl;
}

int main(int argc, char **argv)
{
    Rectangle rec(10, 20);
    Circle cir(10);
    Triangle tri(3, 4, 5);

    Figure fig;
    fig.setDisplay(bind(&Rectangle::display, &rec));
    fig.setArea(bind(&Rectangle::area, &rec));
    func(fig);

    fig.setDisplay(bind(&Circle::display, &cir));
    fig.setArea(bind(&Circle::area, &cir));
    func(fig);

    fig.setDisplay(bind(&Triangle::display, &tri)); 
    fig.setArea(bind(&Triangle::area, &tri));
    func(fig);


    return 0;
}



